package com.daur.uva.engine;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.daur.uva.input.InputMatrix;

public class BoxSorter {

	public List<Integer> sortBoxes(InputMatrix inputMatrix) {
		sortDimensions(inputMatrix);
		EngineContext context = new EngineContext(inputMatrix.getNumberOfBoxes());
		stackBoxes(context, inputMatrix);
		List<Integer> result = findLongestSequence(context);
		return incrementToBoxNumbers(result);
	}

	private void sortDimensions(InputMatrix inputMatrix) {
		for (Integer[] each : inputMatrix.getBoxesWithSizes()) {
			Arrays.sort(each);
		}
	}

	private void stackBoxes(EngineContext context, InputMatrix inputMatrix) {
		Integer[][] boxes = inputMatrix.getBoxesWithSizes();
		for (int i=0; i<boxes.length; i++) {
			for (int j=0; j<boxes.length; j++) {
				if (i==j) {
					continue;
				}
				if (boxOneFitsBoxTwo(boxes[i], boxes[j])) {
					context.addBoxToStack(i, j);
				}
			}
		}
	}

	private boolean boxOneFitsBoxTwo(Integer[] boxOne, Integer[] boxTwo) {
		int boxDimension = boxOne.length;
		for (int i=0; i<boxDimension; i++) {
			if (boxOne[i] >= boxTwo[i]) {
				return false;
			}
		}
		return true;
	}

	private List<Integer> findLongestSequence(EngineContext context) {
		List<Integer> longest = null;
		for (int i=0; i<context.getStackingBoxes().length; i++) {
			List<Integer> list = getStackingStringForBox(i, context.getStackingBoxes());
			if (longest == null || list.size() > longest.size()) {
				longest = list;
			}
		}
		return longest;
	}

	private List<Integer> getStackingStringForBox(int boxNumber, List<Integer>[] stackingBoxes) {
		List<Integer> sequence = new ArrayList<Integer>();
		sequence.add(boxNumber);
		if (stackingBoxes[boxNumber] == null) {
			return sequence;
		}

		List<Integer> longest = null;
		for (Integer each : stackingBoxes[boxNumber]) {
			List<Integer> boxesString = getStackingStringForBox(each, stackingBoxes);
			if (longest == null || boxesString.size() > longest.size()) {
				longest = boxesString;
			}
		}
		sequence.addAll(longest);
		return sequence;
	}

	private List<Integer> incrementToBoxNumbers(List<Integer> sequence) {
		for (int i=0; i<sequence.size(); i++) {
			sequence.set(i, sequence.get(i) + 1);
		}
		return sequence;
	}



}
